﻿#include "exmsg.h"
#include "sys_plat.h"
#include "fixq.h"
#include "debug.h"
#include "mblock.h"
#include "timer.h"
#include "sys_plat.h"
#include "ipv4.h"

static fixq_t msg_queue;
static void *msg_tbl[EXMSG_MSG_CNT]; // 存放定长消息队列中消息的地址
static exmsg_t msg_buffer[EXMSG_MSG_CNT];
static mblock_t msg_block;

/**
 * @brief 创建核心工作线程前的初始化
 */
net_err_t exmsg_init()
{
    DBG_INFO(DBG_EXMSG_LEVEL, "exmsg init begin!");
    net_err_t init_ret = fixq_init(&msg_queue, msg_tbl, EXMSG_MSG_CNT, EXMSG_LOCKER);
    if (init_ret < 0)
    {
        DBG_ERROR(DBG_EXMSG_LEVEL, "fixq init failed in exmsg init!");
        return NET_ERR_SYS;
    }

    init_ret = mblock_init(&msg_block, msg_buffer, sizeof(exmsg_t), EXMSG_MSG_CNT, EXMSG_LOCKER);

    if (init_ret < 0)
    {
        DBG_ERROR(DBG_EXMSG_LEVEL, "block init failed in exmsg init!");
        return NET_ERR_SYS;
    }

    DBG_INFO(DBG_EXMSG_LEVEL, "exmsg init end!");
    return NET_ERR_OK;
}

/**
 * @brief 拉起核心工作线程
 */
net_err_t exmsg_start()
{
    sys_thread_t thread = sys_thread_create(work_thread_entry, (void *)0);
    if (SYS_THREAD_INVALID == thread)
    {
        return NET_ERR_SYS;
    }
    return NET_ERR_OK;
}

/**
 * @brief 对收到的数据进行处理
 */
static net_err_t do_netif_in(exmsg_t *msg)
{
    netif_t *netif = msg->netif.netif;
    pktbuf_t *buf = NULL;
    while (buf = netif_get_in(netif, DELIVER_NO_WAITTIME))
    {
        DBG_INFO(DBG_EXMSG_LEVEL, "recv a pktbuf, size:%d", buf->total_size);

        if (netif->layer)
        {
            net_err_t err = netif->layer->in(netif, buf);
            if (err < NET_ERR_OK)
            {
                DBG_WARNING(DBG_EXMSG_LEVEL, "netif:%s layer of in failed!", netif->name);
                pktbuf_free(buf);
                return err;
            }
        }
        else
        {
            // 自收自发之类的包收到以后通过ip协议向上传
            net_err_t err = ipv4_in(netif, buf);
            if (err < NET_ERR_OK)
            {
                DBG_WARNING(DBG_EXMSG_LEVEL, "netif:%s ipv4 in failed!", netif->name);
                pktbuf_free(buf);
                return err;
            }
        }
    }
    return NET_ERR_OK;
}

static net_err_t do_fun_in(func_msg_t *func_msg)
{
    DBG_INFO(DBG_EXMSG_LEVEL, "call func!");

    func_msg->err = func_msg->func(func_msg);

    DBG_INFO(DBG_EXMSG_LEVEL, "func exec complete!");
    sys_sem_notify(func_msg->wait_sem);
    return func_msg->err;
}

/**
 * @brief 核心工作线程
 */
void work_thread_entry(void *arg)
{
    net_time_t time;
    sys_time_curr(&time); // 获取当前时间

    while (1)
    {
        int firts_timer_curr = timer_first_tmo();

        exmsg_t *msg = fixq_recv(&msg_queue, firts_timer_curr);
        if (msg)
        {
            DBG_INFO(DBG_EXMSG_LEVEL, "recv a msg, type:%d!", msg->type);
            // 对不同类型的消息进行不同的处理
            switch (msg->type)
            {
            case NET_EXMSG_NETIF_IN:
                do_netif_in(msg);
                break;
            case NET_EXMSG_FUN:
                do_fun_in(msg->func);
                break;
            default:
                break;
            }
            mblock_free(&msg_block, msg);
        }

        int dff = sys_time_goes(&time); // 距离传入的time过去了多长时间
        timer_check_tmo(dff);
    }
}

/**
 * @brief 网卡向内存管理器申请内存并向核心线程发送消息
 */
net_err_t exmsg_netif_in(netif_t *netif)
{
    // 申请内存
    exmsg_t *msg = mblock_alloc(&msg_block, DELIVER_NO_WAITTIME);
    if (!msg)
    {
        DBG_WARNING(DBG_EXMSG_LEVEL, "no free block in exmsg block!");
        return NET_ERR_MEM;
    }

    msg->type = NET_EXMSG_NETIF_IN;
    msg->netif.netif = netif;

    // 发送
    net_err_t err = fixq_send(&msg_queue, msg, DELIVER_NO_WAITTIME);
    if (err < NET_ERR_OK)
    {
        mblock_free(&msg_block, msg);
        return err;
    }
    else
    {
        return err;
    }
}

/**
 * @brief 请求工作线程执行特定函数
 * @param func 要执行的回调函数接口
 * @param param 输入的参数
 */
net_err_t exmsg_func_exec(exmsg_func_t func, void *param)
{
    func_msg_t func_msg;
    func_msg.thread = sys_thread_self();
    func_msg.func = func;
    func_msg.param = param;
    func_msg.err = NET_ERR_OK;
    func_msg.wait_sem = sys_sem_create(0);
    if (func_msg.wait_sem == SYS_SEM_INVALID)
    {
        DBG_ERROR(DBG_EXMSG_LEVEL, "wait sem created failed!");
        return NET_ERR_SYS;
    }

    exmsg_t *msg = mblock_alloc(&msg_block, 0);
    if (!msg)
    {
        DBG_WARNING(DBG_EXMSG_LEVEL, "no free block in exmsg block!");
        return NET_ERR_MEM;
    }

    msg->type = NET_EXMSG_FUN;
    msg->func = &func_msg;
    DBG_INFO(DBG_EXMSG_LEVEL, "begin call fun:%p!", &func_msg);

    net_err_t err = fixq_send(&msg_queue, msg, 0);
    if (err < NET_ERR_OK)
    {
        DBG_WARNING(DBG_EXMSG_LEVEL, "send func msg failed!");
        mblock_free(&msg_block, msg);
        return err;
    }

    sys_sem_wait(func_msg.wait_sem, 0);
    DBG_INFO(DBG_EXMSG_LEVEL, "end call fun:%p!", &func_msg);

    return func_msg.err;
}